package com.np.rtmpdump6;

import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.hardware.display.DisplayManager;
import android.hardware.display.VirtualDisplay;
import android.media.MediaCodec;
import android.media.MediaCodecInfo;
import android.media.MediaFormat;
import android.media.projection.MediaProjection;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.view.Surface;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

import androidx.annotation.NonNull;

import com.np.rtmpdump6.RTMPPackage;
import com.np.rtmpdump6.ScreenLive;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.nio.ByteBuffer;

public class VideoCodec extends Thread {
    private MediaProjection mediaProjection;
    private VirtualDisplay virtualDisplay;
    private MediaCodec mediaCodec;
    private ScreenLive screenLive;
    private boolean isLiving;
    private long timeStamp;
    private long startTime;

    public VideoCodec(ScreenLive screenLive) {
        this.screenLive = screenLive;
    }

    public void startLive(MediaProjection mediaProjection) {
        isLiving = true;
        this.mediaProjection = mediaProjection;
        MediaFormat format = MediaFormat.createVideoFormat(MediaFormat.MIMETYPE_VIDEO_AVC, 720, 1280);
        format.setInteger(MediaFormat.KEY_COLOR_FORMAT, MediaCodecInfo.CodecCapabilities.COLOR_FormatSurface);
        format.setInteger(MediaFormat.KEY_BIT_RATE, 400_000);
        format.setInteger(MediaFormat.KEY_FRAME_RATE, 15);
        format.setInteger(MediaFormat.KEY_I_FRAME_INTERVAL, 2);

        try {
            mediaCodec = MediaCodec.createEncoderByType("video/avc");
            mediaCodec.configure(format, null, null, MediaCodec.CONFIGURE_FLAG_ENCODE);
            mediaCodec.start();
        } catch (IOException e) {
            throw new RuntimeException(e);
        }

        // 测试五
        new Thread(new Runnable() {
            @Override
            public void run() {
                ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers();
                while (true) {
                    Bitmap image = stringToBitmap("123");
                    byte[] imageData = bitMapToByteArray(image);
                    ByteBuffer inputBuffer = inputBuffers[0];
                    inputBuffer.put(imageData);
                    mediaCodec.queueInputBuffer(0, 0, imageData.length, 0, 0);
                    try {
                        sleep(100);
                    } catch (InterruptedException e) {
                        throw new RuntimeException(e);
                    }
                }
            }
        }).start();

        // 测试四
//        try {
//
//            Bitmap image = stringToBitmap("123");
//            byte[] inputData = bitMapToByteArray(image);
//
//            ByteBuffer[] inputBuffers = mediaCodec.getInputBuffers();
//            ByteBuffer[] outputBuffers = mediaCodec.getOutputBuffers();
//
//            for (int i = 0; i < 10000; i++) {
//                int inputBufferIndex = mediaCodec.dequeueInputBuffer(100000);
//                if(inputBufferIndex>=0) {
//                    // 将图像数据填充到输入缓冲区
//                    ByteBuffer inputBuffer = inputBuffers[inputBufferIndex];
//                    inputBuffer.clear();
//
//                    // 填充
//                    inputBuffer.put(inputData);
//                    mediaCodec.queueInputBuffer(inputBufferIndex,0,inputData.length,10L,0);
//                }
//            }
//        } catch (
//                IOException e) {
//            e.printStackTrace();
//        }

        // 测试三、https://www.glumes.com/mediacodec-encode-yuv-to-h264/
//        try {
//            //MediaFormat outputFormat = mediaCodec.getOutputFormat(); // option B
//            // 调用 start 进入 Executing 状态，开始编解码工作
//            Bitmap image = stringToBitmap("123");
//            byte[] inputData = bitMapToByteArray(image);
//
//            for (int i = 0; i < 1000000; i++) {
//                image = stringToBitmap("123" + i);
//                //从输入缓冲区队列中取出可用缓冲区，并填充数据
//                int inputBufferId = mediaCodec.dequeueInputBuffer(100000);
//                if (inputBufferId >= 0) {
//                    //ByteBuffer inputBuffer = mediaCodec.getInputBuffer(0);
//                    // fill inputBuffer with valid data     …
//
//                    ByteBuffer inputBuffer = mediaCodec.getInputBuffer(inputBufferId);
//                    // 读取视频帧数据
//                    inputBuffer.put(inputData);
//
//                    mediaCodec.queueInputBuffer(inputBufferId, 0, inputData.length, 10L, 0);
//                }
//            }


//        // 调用 stop 方法进入 Uninitialized 状态
//        mediaCodec.stop();
//        // 调用 release 方法释放，结束操作
//        mediaCodec.release();
//    } catch(
//    IOException e)
//    {
//        e.printStackTrace();
//    }

        // 测试二
//        try {
//            Bitmap image = stringToBitmap("123");
//            byte[] inputData = bitMapToByteArray(image);
//
//            int index = 0;
//            // 循环读取视频和音频数据
//            while (isLiving) {
//                int inputIndex = mediaCodec.dequeueInputBuffer(100000);
//                if (inputIndex >= 0) {
//                    ByteBuffer inputBuffer = mediaCodec.getInputBuffer(inputIndex);
//                    // 读取视频帧数据
//                    inputBuffer.put(inputData);
//                    mediaCodec.queueInputBuffer(inputIndex, 0, inputData.length, 10L, 0);
//                }
//            }
//        } catch (IOException e) {
//            e.printStackTrace();
//        }

        //start();

        // 测试一
//        try {
//            Surface surface = mediaCodec.createInputSurface();
//
//            virtualDisplay = mediaProjection.createVirtualDisplay(
//                    "screen-codec",
//                    720, 1280, 1,
//                    DisplayManager.VIRTUAL_DISPLAY_FLAG_PUBLIC,
//                    surface, null, null);
//
//        } catch (IOException e) {
//            e.printStackTrace();
//        }
    }

    @Override
    public void run() {
        mediaCodec.start();
        MediaCodec.BufferInfo bufferInfo = new MediaCodec.BufferInfo();
        while (isLiving) {
            if (System.currentTimeMillis() - timeStamp >= 2000) {
                Bundle params = new Bundle();
                params.putInt(MediaCodec.PARAMETER_KEY_REQUEST_SYNC_FRAME, 0);
                //dsp 芯片触发I帧
                mediaCodec.setParameters(params);
                timeStamp = System.currentTimeMillis();
            }
            int index = mediaCodec.dequeueOutputBuffer(bufferInfo, 100000);
            if (index >= 0) {
                if (startTime == 0) {
                    startTime = bufferInfo.presentationTimeUs / 1000;
                }
                ByteBuffer buffer = mediaCodec.getOutputBuffer(index);
                byte[] outData = new byte[bufferInfo.size];
                buffer.get(outData);
                RTMPPackage rtmpPackage = new RTMPPackage(outData, (bufferInfo.presentationTimeUs / 1000) - startTime);
                screenLive.addPackage(rtmpPackage);
                mediaCodec.releaseOutputBuffer(index, false);
            }
        }
        isLiving = false;
        mediaCodec.stop();
        mediaCodec.release();
        mediaCodec = null;
        virtualDisplay.release();
        virtualDisplay = null;
        mediaProjection.stop();
        mediaProjection = null;
        startTime = 0;
    }

    /**
     * 由字符串生成 Bitmap 图片
     *
     * @param text
     * @return
     */
    protected Bitmap stringToBitmap(String text) {
        text = "1234567890";

        int textSize = 10;
        int width = 100;
        int height = 100;
        Bitmap bitmap = Bitmap.createBitmap(width, height, Bitmap.Config.ARGB_8888);
        Canvas canvas = new Canvas(bitmap);

        // 设置背景颜色
        canvas.drawColor(Color.WHITE);

        Paint paint = new Paint();
        paint.setColor(Color.BLACK);
        paint.setTextSize(textSize);

        Rect bounds = new Rect();
        paint.getTextBounds(text, 0, text.length(), bounds);

        // 计算文本的宽度和高度
        float x = (bitmap.getWidth() - bounds.width()) / 2f;
        float y = (bitmap.getHeight() - bounds.height()) / 2f;

        // 在画布上绘制文本
        canvas.drawText(text, x, y, paint);

        return bitmap;
    }

    /**
     * Bitmap 转 二进制数组
     *
     * @param bitmap
     * @return
     */
    private byte[] bitMapToByteArray(Bitmap bitmap) {
        ByteArrayOutputStream out = new ByteArrayOutputStream();
        bitmap.compress(Bitmap.CompressFormat.JPEG, 100, out);
        try {
            out.flush();
            out.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        return out.toByteArray();
    }
}
